﻿#ifndef YINSHU_GW_H
#define YINSHU_GW_H
#include "yinshu_gw_defines.h"
#if defined(WIN32)
#ifdef YINSHU_INTERFACE_EXPORTS  
#define YINSHU_INTERFACE_API __declspec(dllexport)   
#else  
#define YINSHU_INTERFACE_API __declspec(dllimport)   
#endif
#else
#if defined(YINSHU_INTERFACE_EXPORTS)
#define YINSHU_INTERFACE_API __attribute__((visibility("default")))
#else
#define YINSHU_INTERFACE_API
#endif 
#endif
#include <string>
#ifdef __cplusplus
extern "C" {
#endif
	//SDK 版本号
    YINSHU_INTERFACE_API const char*  Version();
	
	/**
	* 创建yinshu句柄
	* 业务逻辑 跟随主程序一起创建
	* @return yinshu句柄
	*/
    YINSHU_INTERFACE_API void* CreateYinShuGWInstance();

	/**
	* 销毁yinshu句柄
	* 业务逻辑 在主程序要退出时调用
	* @param handle				yinshu句柄
	*/
    YINSHU_INTERFACE_API void DestoryYinShuGWInstance(void* handle);

	/**
	 * 打开trace日志
	 * @param handle							yinshu句柄
	 * @param enable							日志看开关，enable=true 打开日志，false关闭
	 * @param level	 0-debug,1-warning,2-error
	*/
	YINSHU_INTERFACE_API void EnableSDKTraceLog(void* handle,bool enable,int level,bool remote);

	/**
	* 回收内部资源，在程序结束时调用
	* 业务逻辑 在主程序要退出时调用(先调用DestoryyinshuInstance()，再调用ClearYinshu() )
	*/
    YINSHU_INTERFACE_API void  ClearYinshu();

	/**
	* 初始化yinshuSDK.
	* 业务逻辑 在创建房间时调用
	* @param handle							yinshu句柄
	* @param userData						用户自定义数据
	* @param OnJoined						加入房间回调,调用JoinRoom后会触发
	* @param OnDisConnected					断开连接回调,当此回调被触发时，要依次调用LeaveRoom()， ReleaseSdk()来释放资源
	* @param OnNewMemberJoined				新成员加入房间回调，在此回调中调用SetRenderWindow()接口来设置新成员视频渲染窗口句柄
	* @param OnMemberLeft					成员离开房间回调，其它成员调用LeaveRoom后会触发
	* @param OnMemberEnableVideo			成员打开视频回调
	* @param OnMemberDisableVideo			成员关闭视频回调
	* @param OnMemberUnMuteAudio			成员打开音频回调
	* @param OnMemberMuteAudio				成员关闭音频回调
	* @param OnRemoteModifyMedia			远端打开/关闭本地媒体
	* @param OnSessionError					会话失败回调，会话失败的原因包括设备被占用，网络堵塞导致消息超时，消息内容错误等等
	*/
    YINSHU_INTERFACE_API void  InitSDK(
		void* handle,
		void* userData,
		int waitTime,   //秒
		void(*OnJoined)(void* userData, ErrorCode eCode),
		void(*OnDisConnected)(void* userData),
		void(*OnNewMemberJoined)(void* userData, const char* pMemberId, const char* pDisplayName, const char* role),
		void(*OnMemberLeft)(void* userData, const char* pMemberId, const char* pDisplayName),
		void(*OnMemberEnableVideo)(void* userData, const char* pMemberId, const char* pDisplayName, VideoType type),
		void(*OnMemberDisableVideo)(void* userData, const char* pMemberId, const char* pDisplayName, VideoType type),
		void(*OnMemberUnMuteAudio)(void* userData, const char* pMemberId, const char* pDisplayName),
		void(*OnMemberMuteAudio)(void* userData, const char* pMemberId, const char* pDisplayName),
		void(*OnRemoteModifyMedia)(void* userData, const char* pKind, bool bOpen),
		void(*OnRecvUserMessage)(void* userData, const char* pHistoryMessage),
		void(*OnSessionError)(void* userData, const char* reason),
		void(*OnCanDownDisconnectedActive)(void* userData, const char* pMemberId),
		void(*OnRoomEnd)(void* userData) = nullptr,
		void(*OnMemberRoleChanged)(void* userData, const char* pMemberId, const char* role) = nullptr,
		void(*OnChangeResolution)(void* userData, int width, int height) = nullptr, 
		void(*OnRecvSignal)(void* userData, const char* method, const char* jsonStr) = nullptr,
		void(*OnIatResultCallBack)(void* userData, const char* pRoomId, const char* pResult)=nullptr);

	/**
	* 销毁yinshuSDK内部资源.
	* 业务逻辑 在销毁房间时调用
	* @param handle					yinshu句柄
	*/
    YINSHU_INTERFACE_API void  ReleaseSdk(
		void* handle);

	/**
	* 加入房间.
	* 业务逻辑 在创建房间后，主动开启视频会议时调用
	* @param handle					yinshu句柄
	* @param pRoomId						房间号
	* @param eMediaType						媒体会话类型
	* @param pMemberId						成员标识符，必须在当前房间中保持唯一
	* @param pDisplayName					成员昵称
	* @param pServerIp						服务器IP
	* @param nPort							服务器端口
	* @param pToken							认证信息,此为预留接口，目前还没有认证，这里可以给一个任意字符串
	*/
    YINSHU_INTERFACE_API void  JoinRoom(
		void* handle,
		const char* pRoomId,
		MediaType eMediaType,
		const char* pMemberId,
		const char* pDisplayName,
		const char* pServerIp,
		int nPort,
		const char* pToken,
		int pix_fmt = 12,
		bool recv = false,
		const char* role = "tutor"
	);
	/**
	* 加入房间.
	* 业务逻辑 在创建房间后，主动开启视频会议时调用
	* @param handle					yinshu句柄
	* @param dispatchServer						调度服务器
	* @param pRoomId						房间号
	* @param passwd							房间密码
	* @param eMediaType						媒体会话类型
	* @param pMemberId						成员标识符，必须在当前房间中保持唯一
	* @param pDisplayName					成员昵称
	* @param avatarUrl						成员头像链接
	* @param role							成员校色
	* @return const char*					返回值为json字符串，NULL表示失败，否则返回形式如{"code":0,"message":"sucessful"};
	*/
	YINSHU_INTERFACE_API const char* JoinRoom2(
		void* handle,
		const char* dispatchServer,
		const char* pRoomId,
		const char* passwd,
		MediaType eMediaType,
		const char* pMemberId,
		const char* pDisplayName,
		int pix_fmt = 12,
		bool recv = false);
	/**
	* 离开房间.
	* 业务逻辑 在创建房间后，主动关闭视频会议时调用
	* @param handle					yinshu句柄
	*/
    YINSHU_INTERFACE_API void  LeaveRoom(
		void* handle);

    YINSHU_INTERFACE_API void  RestartMedia(void* handle);


	/*******************************************
	* 以下为流媒体相关接口
	*/

	/**
	* @param handle                     yinshu句柄
	* @param pMemberId                  成员标识符
	* @param type						数据类容类型，VideoCam表示摄像头视频流，VideoScreen 屏幕共享流
	* @param PullMemberVideoData 		接收指定成员数据回调，data代表单帧数据，datalen代表单帧数据长度
	*/
    YINSHU_INTERFACE_API void  PullMemberVideoDataFunc(
		void* handle,
		const char* pMemberId,
		VideoType type,
		void(*PullMemberVideoData)(void* userData, const char* pMemberId, const char* codec, unsigned char *data, int datalen, unsigned timestamp));

	/**
	* @param handle                     yinshu句柄
	* @param pMemberId                  成员标识符
	* @param PullMemberAudioData  		接收指定成员数据回调，每10ms一次
	*/
    YINSHU_INTERFACE_API void  PullAudioDataFunc(
		void* handle,
		const char* pMemberId,
		void(*PullMemberAudioData)(void* userData, const char* pMemberId, const char* codec, char *buffer, int datalen, int sample_rate, int input_channels, unsigned timestamp));

    YINSHU_INTERFACE_API void  PullAudioEncodeData(
		void* handle,
		const char* pMemberId,
		void(*PullMemberAudioEncodeData)(void* userData, const char* pMemberId, const char* codec, char *buffer, int datalen, int sample_rate, int input_channels, unsigned timestamp));
	

	/*
	*@param voeEnginePlayoutMs				音频引擎取数据时间间隔
	*/

    YINSHU_INTERFACE_API void  SetVoeEnginePlayoutIntervalMs(
		void* handle, 
		int intervam_ms);

	/**
	* 发送自己的视频流
	* 业务逻辑 
	* @param handle                     yinshu句柄
	* @param codec                      编码类型
	* @param nalu_array                 单帧视频数据，每个nalu开头必须包含startcode
											如果是关键帧，则数据从IDR数据(nalType=5)开始，不必包含sps/pps
	* @param nalu_len_array             nalu数据长度的数组
	* @param array_size             	nalu数组的size
	* @param width                      宽度
	* @param height                     高度
	* @param key_frame                  是否为关键帧
	* @param sps                  		如果是关键帧，则传入sps数据，非关键帧传入NULL即可
	* @param sps_length                 sps数据长度
	* @param pps                  		如果是关键帧，则传入pps数据，非关键帧传入NULL即可
	* @param sps_length                 pps数据长度
	*/
    YINSHU_INTERFACE_API int  PushMemberVideoDataFunc(
		void* handle,
		const char* codec,
		unsigned char** nalu_array,
		int* nalu_len_array,
		int array_size,
		int width,
		int height,
		bool key_frame,
		unsigned char *sps,
		int sps_length,
		unsigned char *pps,
		int pps_length,
		long timestamp);

	/**
	* 发送自己的音频流
	* 业务逻辑 
	* @param handle                     yinshu句柄
	* @param codec                      编码类型，目前只支持pcm数据
	* @param buffer                     pcm数据
	* @param size                    	数据长度
	* @param sample_rate                采样率，目前只支持48000
	* @param input_channels             声道，目前只支持双声道
	*/
    YINSHU_INTERFACE_API int  PushMemberAudioDataFunc(
		void* handle,
		const char* codec,
		const char* buffer,
		int size,
		int sample_rate, 
		int input_channels,
		long timestamp
	);

	/**
	* 打开指定成员视频(包括自己)
	* 业务逻辑 默认状态下是接受所有房间成员视频，如果调用过DisableMemberVideo()后，可以通过此接口接收指定成员视频
	* @param handle						yinshu句柄
	* @param pMemberId					成员标识符
	* @param EnableMemberVideoResult	接收指定成员视频回调
	*/
    YINSHU_INTERFACE_API void  EnableMemberVideo(
		void* handle,
		const char* pMemberId,
		void(*EnableMemberVideoResult)(void* userData, bool bSucc, const char* pMemberId));

	/**
	* 关闭指定成员视频(包括自己)
	* 业务逻辑 默认状态下是接受所有房间成员视频，通过此接口可以不接收指定成员视频
	* @param handle						yinshu句柄
	* @param pMemberId					成员标识符
	* @param DisableMemberVideoResult	不接收指定成员视频回调
	*/
    YINSHU_INTERFACE_API void  DisableMemberVideo(
		void* handle,
		const char* pMemberId,
		void(*DisableMemberVideoResult)(void* userData, bool bSucc, const char* pMemberId));

	/**
	* 打开指定成员音频(包括自己)
	* 业务逻辑 默认状态下是接受所有房间成员音频，如果调用过DisableMemberAudio()后，可以通过此接口接收指定成员音频
	* @param handle						yinshu句柄
	* @param pMemberId					成员标识符
	* @param EnableMemberVideoResult	接收指定成员音频回调
	*/
    YINSHU_INTERFACE_API void  EnableMemberAudio(
		void* handle,
		const char* pMemberId,
		void(*EnableMemberAudioResult)(void* userData, bool bSucc, const char* pMemberId));

	/**
	* 关闭指定成员音频(包括自己)
	* 业务逻辑 默认状态下是接受所有房间成员音频，通过此接口可以不接收指定成员音频
	* @param handle						yinshu句柄
	* @param pMemberId					成员标识符
	* @param DisableMemberAudioResult	不接收指定成员视频回调
	*/
    YINSHU_INTERFACE_API void  DisableMemberAudio(
		void* handle,
		const char* pMemberId,
		void(*DisableMemberAudioResult)(void* userData, bool bSucc, const char* pMemberId));

	/**
	* 请求关键帧
	* @param handle						yinshu句柄
	* @param pMemberId					成员标识符
	*/
    YINSHU_INTERFACE_API void  RequestKeyFrame(
		void* handle,
		const char* pMemberId);

	/**
	* 指定媒体流大小
	* @param handle						yinshu句柄
	* @param pMemberId					成员标识符
	* @param profile					媒体流大小  “high” 或 “low”
	*/
    YINSHU_INTERFACE_API void  SetMemberProfile(
		void* handle,
		const char* pMemberId,
		const char* profile
	);

	/*******************************************
	* 其他接口
	*/

	/**
	* 发送用户自定义数据.
	* @param handle						yinshu句柄
	* @param data						json格式数据内容
	*/
    YINSHU_INTERFACE_API void  SendUserMessage(
		void* handle,
		const char* data);


	/**
	* 发送用户自定义数据.
	* @param handle						yinshu句柄
	* @param OnGetUserMessageHistory	消息内容回调，data为json格式
	*/
    YINSHU_INTERFACE_API void  GetUserMessageHistory(
		void* handle,
		void(*OnGetUserMessageHistory)(void* userData, const char* data));

	/**
	* 举手/取消举手

	* @param handle						yinshu句柄
	* @param pMemberId					成员ID
	* @param bUp						当bUp为true时举手， 为false时 取消举手
	*/
    YINSHU_INTERFACE_API void  RaiseHand(
		void*		handle,
		const char*	pMemberId,
		bool		bUp);

	/**
	* 设置收到举手消息时的回调

	* @param handle						yinshu句柄
	* @param OnRaiseHand				回调
	*/
    YINSHU_INTERFACE_API void  SetRaiseHandCallback(
		void* handle,
		void(*OnRaiseHand)(void* userData, const char* pMemberId, bool bUp));

	/**
	* 打开/关闭成员的音/视频

	* @param handle						yinshu句柄
	* @param pMemberId					成员ID
	* @param type						媒体类型 “video” 视频， “audio“ 音频 
	* @param bOpen						当bOpen为true打开， 为false时 关闭
	*/
    YINSHU_INTERFACE_API void  ModifyMemberMediaStatus(
		void*		handle,
		const char*	pMemberId,
		const char* type,
		bool		bOpen);


	/**
	* 指定大屏发言人

	* @param handle						yinshu句柄
	* @param pMemberId					成员ID
	*/
    YINSHU_INTERFACE_API void  SetCurrentActiveMember(
		void*		handle,
		const char* pMemberId
	);

	/**
	* 踢出房间

	* @param handle						yinshu句柄
	* @param pMemberId					成员ID
	* @param displayName				昵称
	*/
    YINSHU_INTERFACE_API void  KickMember(
		void*		handle,
		const char* pMemberId,
		const char* displayName
	);

    /**
	* 切换成员角色 （只能在student和visitor之间切换）

	* @param handle						yinshu句柄
	* @param vtosMemberId				visitor 转 student 的成员ID
	* @param stovMemberId				student 转 visitor 的成员ID  
	*/
    YINSHU_INTERFACE_API void  ChangeMemberRole(
		void*		handle,
		const char* vtosMemberId = nullptr,
		const char* stovMemberId = nullptr
	);

	typedef void* (*SignalCallBackFun)(const char* data, void* userdata);
	/*
	* 发送系统信令
	* @param handle		yinshu句柄
	* @param sigName	信令名称
	* @param jsonStr	信令参数 json格式字符串
	* @param successCallBack	成功回调
	* @param failCallBack		失败回调
	*/
    YINSHU_INTERFACE_API void  SendSignal(
            void* handle,
            const char* sigName,
            const char* jsonStr,
            SignalCallBackFun successCallback = nullptr,
            SignalCallBackFun failedCallback = nullptr);

	/*
	* 更新昵称 （备注：修改名称成功后，需要更新SDK缓存的昵称）
	* @param handle			yinshu句柄
	* @param displayName	昵称
	*/
    YINSHU_INTERFACE_API void  UpdateDisplayName(void* handle,
                                                 const char* displayName);

    YINSHU_INTERFACE_API void   ChangeScreenMode(void* handle, bool bHorizontal);

    YINSHU_INTERFACE_API void   UseCostumPTS(void* handle, bool bUse = true);
	//目前这个录制只能会议混音，需要进一步处理
    YINSHU_INTERFACE_API void   StartRecord(void* handle, const char* path_fileName=NULL);
    YINSHU_INTERFACE_API void   StopRecord(void* handle);

	//进行AI会议纪要生成
	YINSHU_INTERFACE_API void EnableIatWriter(void* handle, const char* jsonSettingStr);
	YINSHU_INTERFACE_API void DisableIatWriter(void* handle);

#ifdef __cplusplus
}
#endif
#endif
